package br.ufpe.eonsimulator.business;

import java.util.List;

import org.apache.log4j.Logger;

import br.ufpe.eonsimulator.domain.Connection;
import br.ufpe.eonsimulator.domain.LinksCostWrapper;
import br.ufpe.eonsimulator.domain.Route;
import br.ufpe.eonsimulator.domain.Simulation;
import br.ufpe.eonsimulator.rsa.RSAWrapper;
import br.ufpe.simulator.list.FixedArrayList;

/**
 * A simple simulation approach based on creating connection requests.
 */
public class OfflineSimulationController extends AbstractSimulationController
		implements IsSimulationController {

	// Private class for Simulation Route information
	private static Logger logger = Logger
			.getLogger(OfflineSimulationController.class);

	@Override
	public void run(Simulation simulation) {
		int numberOfIterations = simulation.getNumberOfIterations();
		List<LinksCostWrapper> linksCostWrappers = new FixedArrayList<LinksCostWrapper>(
				simulation.getSimulationResultSetSize());
		for (int i = 0; i < numberOfIterations; i++) {
			simulation.clearArrivalRate();
			simulation.getTopology().updateLinksCost(i,
					simulation.getLinkCostFunction(), simulation.getAlfa(),
					linksCostWrappers);
			do {
				clearSimulation(simulation, logger);
				for (int numberConnectionIndex = 0; numberConnectionIndex < simulation
						.getMaxNumberConnection(); numberConnectionIndex++) {
					simulation.clearElapsedConnections(); // Removes all the
															// connections with
															// elapsed time;
					// Defines the node pair, the bit rate and the death time of
					// the
					// connection
					Connection connection = simulation.getTrafficGenerator()
							.createConnection(simulation);
					simulation.getSimulationResults()
							.incrementNumberOfRequests();
					simulation.getSimulationResults().incrementNumberOfRequest(
							connection.getRequestedBitRate());
					// Calculate the routes using the routing algorithm
					List<Route> routes = simulation.getIsRoutingAlgorithm()
							.createRoutes(connection, simulation.getTopology(),
									simulation.getCostFunction());

					if (routes != null && !routes.isEmpty()) {
						List<RSAWrapper> simulationRouteWrappers = simulation
								.getRSAAlgorithm().getQoTRSAWrapper(routes,
										simulation, connection);
						for (RSAWrapper rsaWrapper : simulationRouteWrappers) {
							simulation.getTopology().updateAllocatedSlots(
									rsaWrapper.getRoute(),
									rsaWrapper.getnSlots());
							simulation.getTopology().updateAllocatedSlots(
									simulation.getTopology().getDualRoute(
											rsaWrapper.getRoute()),
									rsaWrapper.getnSlots());

						}
					}
				}
			} while (simulation.nextSimulation());
		}
		simulation.getOutputLinkCostFunction().write(linksCostWrappers);
	}
}
